home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr53 / 312_01.zip / TLR2MAK.AWK < prev   
Text File  |  1993-04-22  |  15KB  |  343 lines

  1. #  HEADER:        ;
  2. #  TITLE:         Turbo Link Response file object file extractor
  3. #  DATE:          09/20/1989;
  4. #  VERSION:       1.2;
  5. #  DESCRIPTION:   "An AWK program which scans a link-configuration
  6. #                 file and builds a batch file which will in turn
  7. #                 produce a make-file.  Requires the services of a
  8. #                 source-file dependency generator (such as cincdep)."
  9. #  KEYWORDS:      Makefile, make, include, dependency generator;
  10. #  SYSTEM:        MS-DOS;
  11. #  WARNINGS:      "Filenames are assumed to contain only characters from
  12. #                 the limited set [A-Za-z_0-9.].  Your TLR file must
  13. #                 contain all of the object files which you want scanned
  14. #                 for dependencies, as well as the executable file name."
  15. #                 PolyAwk will generate false matches to lines
  16. #                 beginning with non-ASCII (i.e. 128..256) chars."
  17. #  FILENAME:      TLR2MAK.AWK;
  18. #  SEE-ALSO:      CINCDEP.AWK, CF2MAK.AWK, AINCDEP.AWK, PINCDEP.AWK;
  19. #  AUTHORS:       James Yehle;
  20. #  COMPILERS:     PolyAWK, Mortice Kern AWK, Rob Duff's PC-AWK 2.0;
  21. #
  22. #-----------------------------------------------------------------------------
  23. #
  24. #  TLR2mak.awk              Last modified  Sep 20, 1989  12:54
  25. #
  26. #     Scans an Turbo Link response file to produce a batch file for
  27. #     use with cincdep.awk to build a set of make-file dependency lists
  28. #
  29. #  Jim Yehle  753 Left Fork Rd. #B/Sugarloaf Star Route/Boulder, CO 80302 9252
  30. #
  31. # . . . Revision history . . . . . . . . . . . . . . . . . . . . . . . . . . .
  32. #
  33. #       Sep 10 89  JRY  -- Released for C User's Group distribution --
  34. #  1.2  Sep 10 89  JRY  Added legal-filename-char regular expression
  35. #  1.1  Sep 8  89  JRY  Added "verbose" CO output as debug level 1.
  36. #  1.0  Aug 31 89  JRY  Initial creation.. adapted from Intel bind-
  37. #                        configuration file extractor CF2MAK.AWK (v 1.5).
  38. # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  39. #
  40. #  Usage is:
  41. #    awk -f tlr2mak.awk filename.tlr outfile=[path]filename
  42. #        lc=command lcf=[p][n][e] [>batchfile]
  43. #     where outfile gets the conglomerated dependency generator output
  44. #     Order of command-line parameters (save for "-f ..." 
  45. #      and ">batchfile") is irrelevant, but identifiers must be in lower case.
  46. #     lc is the compile command (no spaces allowed)
  47. #     lcf controls which components of the source file's name get
  48. #         included in the link command line: p = directory path,
  49. #         n = name, e = extension.
  50. # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  51. #
  52. #  Takes a Turbo Link response file as input.  Assumes that the portion of the
  53. #   TLINK command line containing the object file list and the executable file 
  54. #   is put into a "Turbo Link Response" file.  The linker must be invoked via a
  55. #   form such as "TLINK /c c0s @bawk.tlr,bawk.map,emu maths cs", where BAWK.TLR
  56. #   might contain "o:\bawk o:\bawkdo o:\bawkact o:\bawkpat o:\bawksym, o:\bawk".
  57. #   Alternatively, you could just put the whole business into BAWK.TLR and
  58. #   tell the linker "TLINK @bawk.tlr".
  59. #  Generates an executable-dependency list at the start of outfile,
  60. #   followed by the link command and the primary (executable) file name.
  61. #  Extracts all object file names.
  62. #  Generates a batch file line, for each object file found, of the form:
  63. #   comdpre srcfile "incpath="incpath "objname="file.obj
  64. #     "cc="cc "ccf="ccf comdmid outfile comdpost
  65. #  unless the source file can't be found, in which case it makes this line:
  66. #   comdpre "__NOFILE__ objname="file.obj "cc= ccf= " comdmid outfile comdpost
  67. #  The search for the source file covers C files only, but can be easily
  68. #   extended to support other languages. (See example in CF2MAK.AWK.)
  69. #
  70. #  Assumes object file names contain only these chars: [A-Za-z0-9_]*.obj
  71. # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  72. #
  73. # Turbo Link (response file) rules:
  74. #
  75. #  Lines can be continued by putting a '+' at the end of line
  76. #  Unterminated line is taken as a comma 
  77. #
  78. #  Turbo Link's command-line invocation form is:
  79. #   TLINK /options objfile objfile ..., exefile, mapfile, libfile libfile ... 
  80. #  Everything past TLINK can come from a response file, as in TLINK @exe.tlr
  81. #
  82. #-----------------------------------------------------------------------------
  83. #
  84. BEGIN {
  85.    #  Cf2mak supports several languages.  Each language must have
  86.    #   1) a source file name extension to replace object file extension (.obj)
  87.    #   2) a source directory pathname (stuck on front of file name during search)
  88.    #   3) an include-file directory whose name to pass to a dependency scanner
  89.    #   4) a compiler command to pass to dependency scanner (no spaces allowed)
  90.    #   5) controls for filename pathname/extension inclusion in compile command line
  91.    #   6) a dependency generator awk program
  92.  
  93.    # Language 1 is C
  94.    ext[1] = ".c"
  95.    path[1]    = "s:\\c\\"
  96.    ipath[1]   = "s:\\c\\inc\\"
  97.    cc[1] = "ccc"
  98.    ccf[1] = "n"
  99.    depgen[1] = "s:\\awk\\cincdep.awk"
  100.  
  101.    # Set various strings used in building batch-file command lines
  102.  
  103.    #    allpre      Leading line(s) of entire batch file
  104.    #    allpost     Trailing line(s) of entire batch file
  105.    #    comment     Comment-line lead-in: DOS "REM" or "ECHO", iRMX ";"
  106.    #    comdpre     Command line prefix
  107.    #    comdmid     Command line midle: between source & output file names
  108.    #    comdpost    Command line suffix
  109.    #    linecont    Line-continuation EOL char: snake " /", unix make "\"
  110.    #    fname_chars Regular expression specifying any single legal char
  111.    #                which can appear in a file name.  Must exclude 
  112.    #                directory path separator character! (DOS \, UNIX /)
  113.    allpre = "echo off"
  114.    allpost = "echo on"
  115.    comment = "echo "
  116.    comdpre = "awk -f "
  117.    comdmid = " >>"
  118.    comdpost = ""
  119.    linecont = " \\"
  120.    fname_chars = "[^\\\\ :]" # Unix "[^/ ]"; used to use "[A-Za-z0-9_]"
  121. #
  122.    co = "CON"   # Console-out: MS-DOS "CON", iRMX ":co:", unix "/dev/tty"
  123.    debug = 0    # 0=off, 1=verbose, 2=main-level debug, 3= adds functions
  124.  
  125.    print "tlr2mak.awk  Bind configuration object-file extractor  v 1.2" > co
  126.  
  127.    outfile = get_cl_param( "outfile=", 0)
  128.    lc = get_cl_param( "lc=", 0)
  129.    lcf = get_cl_param( "lcf=", 0)
  130.  
  131.    print allpre
  132.  
  133.    field = "objs"
  134.    field_end = 0
  135. }
  136. #
  137. {
  138.    gsub( /[\t]/, " ", $0) # Tabs -> spaces; re-parse $0
  139.  
  140.    # If line-continuer is glued to a fname, push it into next fname
  141.    sub( /\+$/, " +", $0) # (forces re-parsing of $0 into $1..$NF+1)
  142.    if (debug>1)
  143.       print "Line #" NR " has " NF " fnames:" >co
  144.    # Preserve NF, $1..$NF; since sub-functions' getline() will change them
  145.    nfnames = NF
  146.    for (f = 1; f <= NF; ++f) {
  147.       fname[f] = $f
  148.       if (debug>1)
  149.          print " -> fname[" f "] = '" $f "'." >co
  150.    }
  151.  
  152.    # Process each file name (i.e. word, or $1..$NF) in the line
  153.    for (f = 1; f <= nfnames; ++f) {
  154.       if (debug>1)
  155.          printf( "Processing fname[%d]: '%s'\n", f, fname[f]) >co
  156.       if (f==nfnames && fname[f]=="+") {
  157.          if (debug>1)
  158.             printf("Last fname[%d] == \"+\" (\"%s\")\n", f, fname[f]) >co
  159.          break
  160.       }  
  161.       if ( fname[f] ~ /^\// ) { # 1st char is '/':  its an /option
  162.          field_end = 0
  163.          if (debug>1)
  164.             print " ..it's an option." >co
  165.          continue
  166.       }
  167.       # If fname ends with a comma, remove it; stop after this fname
  168.       field_end = sub( /,$/, "", fname[f] )
  169.       if (field=="exe") { # Get executable-file name
  170.          # Split executable file name into Path, Name, and Extension components
  171.          split_filename( fname[f], exefile, fname_chars)
  172.          if (exefile["ext"]=="") { /* Turbo Link assumes ".EXE" extension
  173.             if (debug>1)
  174.                printf( " \".EXE\" added to executable-name \"%s\"\n",
  175.                        exefile["path"] exefile["name"]              ) >co
  176.             exefile["ext"]==".EXE")
  177.          }
  178.          if (debug>1) 
  179.             printf( "Executable file name components: '%s' '%s' '%s'\n",
  180.                      exefile["path"], exefile["name"], exefile["ext"]  ) >co
  181.          exit
  182.       }
  183.       # Object file name has been extracted (into fname[f])
  184.       if (debug>1)  print " ..it's an object file." >co
  185.       fullobjname = fname[f]
  186.  
  187.       split_filename( fullobjname, objnameparts, fname_chars)
  188.  
  189.       # If extension missing, add ".OBJ" (This is Turbo Link's rule.)
  190.       if (objnameparts["ext"]=="") {
  191.          if (debug>1)
  192.             printf(" \".OBJ\" added to object file name \"%s\"\n",
  193.                    objnameparts["path"], objnameparts["name"]    ) >co
  194.          objnameparts["ext"] = ".OBJ"
  195.          fullobjname = fullobjname ".OBJ"
  196.       }
  197.       for (flix=1; flix in flist; flix++)
  198.          ;
  199.       flist[flix] = fullobjname # Add to array
  200.  
  201.       # Generate one batch file line
  202.       look_for_source_file( objnameparts["name"], fullobjname)
  203.  
  204.       if (field_end) {
  205.          field = "exe"
  206.          if (debug>1) print "End of object-files section."
  207.       }
  208.    }
  209.  
  210.    if (fname[nfnames] != "+") {
  211.       field = "exe"
  212.       if (debug>1) 
  213.          printf( "fname[%d] != \"+\" (\"%s\"): end of object-files section.\n",
  214.                  nfnames, fname[nfnames]                                   ) >co 
  215.    }
  216.  
  217. }
  218. #
  219. END {
  220.    print allpost
  221.  
  222.    # Generate executable-file dependency list (into outfile)
  223.    # Print primary (executable) file name before list (left of colon)
  224.    primarydependent = sprintf( "%s%s%s", exefile["path"],
  225.                                exefile["name"], exefile["ext"])
  226.    printf( "%s:", primarydependent) >outfile
  227.    if (debug) printf( "%s:", primarydependent) >co
  228.    linelen = length(primarydependent) + 1
  229.    for (i=1; i in flist; i++) {
  230.       # If line will be too long, put out a line-continuation char and newline
  231.       if (linelen + 1 + length(flist[i]) + length(linecont)  > 79) {
  232.          printf( "%s\n", linecont) >outfile
  233.          if (debug) printf( "%s\n", linecont) >co
  234.          # On the new line, tab out to underneath the first included file name
  235.          for (linelen=0; linelen<length(primarydependent)+1; ++linelen) {
  236.             printf(" ") >outfile
  237.             if (debug) printf(" ") >co
  238.          }
  239.       }
  240.       printf( " %s",  flist[i] ) >outfile
  241.       if (debug) printf( " %s",  flist[i] ) >co
  242.       linelen += length(flist[i]) + 1
  243.    }
  244.    # Build the link command line's only parameter: the filename
  245.    #  depending on options specified in lcf command-line param
  246.    link_comd_filename = sprintf( "%s%s%s",
  247.                                  lcf ~ /[Pp]/? exefile["path"] : "",
  248.                                  lcf ~ /[Nn]/? exefile["name"] : "",
  249.                                  lcf ~ /[Ee]/? exefile["ext"]  : "" );
  250.    printf( "\n\t%s %s\n\n", lc, link_comd_filename) >outfile
  251.    if (debug) printf( "\n\t%s %s\n\n", lc, link_comd_filename) >co
  252.  
  253. }
  254. #
  255. function look_for_source_file( name,    # File name: without path nor extension
  256.                                objname, # Object file's full name (for batch line)
  257.                                srcname, # Local var: complete source file name
  258.                                lang)    # Local var: loop index
  259. #  Looks for source file name, using dir path/extension for each language
  260. #  Generates a batch file dependency generator line for proper language
  261. #  if file name found; otherwise makes a __NOFILE__ line for language #1
  262. {
  263.    if (debug>2) 
  264.       print "look_for_source_file(name=" name ", objname=" objname ")" >co
  265.    for (lang in ext) { # For each language supported
  266.       # Build source file name
  267.       #  using this language's directory pathname and extension
  268.       srcname = path[lang] name ext[lang]
  269.       if (debug>2) 
  270.          print "look_for_source_file(), lang #" lang ": srcname = " srcname >co
  271.       # See if the file exists, by reading 1st line of it
  272.       # (getline returns -1 on error.. assume that means file not found)
  273.       if (getline <srcname != -1) { # caution.. getline fills $0, $1 ...
  274.          # File found.. Build the normal batch file line
  275.          printf( "%s %s %s ", comdpre, depgen[lang], srcname)
  276.          printf( "incpath=%s objname=%s ", ipath[lang], objname)
  277.          printf( "cc=%s ccf=%s ", cc[lang], ccf[lang] )
  278.          printf( "%s %s %s\n", comdmid, outfile, comdpost)
  279.          if (debug) printf( "%s %s %s ", comdpre, depgen[lang], srcname) >co
  280.          if (debug) printf( "incpath=%s objname=%s ", ipath[lang], objname) >co
  281.          if (debug) printf( "cc=%s ccf=%s ", cc[lang], ccf[lang] ) >co
  282.          if (debug) printf( "%s %s %s\n", comdmid, outfile, comdpost) >co
  283.          close( srcname)
  284.          return
  285.       }
  286.       else {
  287.          if (debug>2)
  288.             print "look_for_source_file(): " srcname " not found." >co
  289.          continue;
  290.       }
  291.    }
  292.    # File not found--all language extensions/paths tried
  293.    print comment "TLR2MAK.AWK Warning: \"" name "\" source file not found."
  294.    print "TLR2MAK.AWK Warning: \"" name "\" source file not found." > co
  295.    print comdpre " " depgen[1] " __NOFILE__ objname=" objname " cc= ccf= " comdmid outfile comdpost
  296. }
  297. #
  298. function get_cl_param( parname,  # Which parameter ya lookin' fer? (e.g. "blah=")
  299.                        optional) # Is it an optional parameter?
  300. # Search the ARGV[] array for a command-line parameter beginning w/ parname
  301. # If optional is 0, aborts program if not found
  302. # Returns the string to the right of the '='
  303. {
  304.    for (i in ARGV)
  305.       if (match(ARGV[i],parname))
  306.          return substr(ARGV[i],length(parname)+1)
  307.  
  308.    if (optional)
  309.       return ""
  310.  
  311.    printf( "tlr2mak.awk usage error:  Command-line parameter '%s' missing\n",
  312.            parname )                                                      > co
  313.    exit 1  # Abort
  314. }
  315. #
  316. function split_filename( name,        # In: The full file name
  317.                          shards,      # Out:array which receives ["path"],
  318.                                       #     ["name"] and ["ext"] members
  319.                          fname_chars, # In: Regular expression which matches
  320.                                       #     any single file-name character.
  321.                                       #     (must exclude directory separator)
  322.                          # Local variables:
  323.                          pnsep,       # Path/Name separator (1st char of Name)
  324.                          nesep)       # Name/Extension separator (1st Ext char)
  325.  
  326. # Split a file name into three components: Path, Name, and Extension 
  327. {
  328.    pnsep = match( name, fname_chars"*$")
  329.    shards["path"] = substr( name, 1, pnsep-1)
  330.    nesep = match( name, "\\."fname_chars"*$")
  331.    if (debug>2)
  332.       print "in \"" name "\", name starts @ " pnsep ", ext @ " nesep >co
  333.    if (nesep==0) {
  334.       shards["name"] = substr( name, pnsep)
  335.       shards["ext"] = ""
  336.    }
  337.    else {
  338.       shards["name"] = substr( name, pnsep, nesep-pnsep)
  339.       shards["ext"] = substr( name, nesep)
  340.    }
  341. }
  342.  
  343.